package basicexmaple;

import eduni.simjava.*;

/**
 * Clase Ejemplo simulacion
 *
 * @author eagle
 */
class Example1 {

    public static void main(String args[]) {
        Sim_system.initialise();
        //Instanciamos calse del sender
        Sim_system.add(new Source("Sender", 1, Source.SRC_OK));
        //Instanciamos calse del Receiver 
        Sim_system.add(new Sink("Receiver", 2, Sink.SINK_OK));
        //Comunicamos los puertos de las dos entidades
        Sim_system.link_ports("Sender", "out", "Receiver", "in");
        //Arrancamos la simulacion
        //Sim_system.generate_graphs(true);
        Sim_system.run();
    }
}

/**
 * Clase del sender
 *
 * @author eagle
 */
class Source extends Sim_entity {

    private Sim_port out;
    //index:nivel de la simulacion. Sender 1; Receiver 2
    private int index;
    //estado de la simulacion
    private int state;
    //Variables para controlar el estado de la simulacion, index y estado
    public static final int SRC_OK = 0;
    public static final int SRC_BLOCKED = 1;

    public Source(String name, int index, int state) {
        //name: Nombre asociado a la entidad
        super(name);
        this.index = index;
        this.state = state;
        out = new Sim_port("out");
        //Agregamos un puerto a la entidad.
        add_port(out);
    }

    /**
     * Sobreescribimos el método body
     */
    @Override
    public void body() {
        //creamos el evento
        Sim_event ev = new Sim_event();
        int i;

        System.out.println("Haciendo el body del sender: ");
        for (i = index; i < 100; i++) {

            /**
             * sim_schedule: envia un evento a otra entidad a través de un
             * puerto, sin datos.
             *
             * Parametro 1: Puerto a traves del cual enviamos el evento
             * Parametro 2: delay: Cantidad de tiempo que debera demorar el
             * evento. Parametro 3: tag: numero definido por el usuario que
             * representa el tipo de evento.
             */
            sim_schedule(out, 0.0, i);
            //tiempo de espera
            sim_wait(ev);
            state = SRC_BLOCKED;
            sim_hold(0.2);
            state = SRC_OK;

//            Double ev1 = (Double) ev.get_data();
//            Integer ev2 = (Integer) ev.get_data();

            /**
             * sim_trace Escribe un mensaje de seguimiento de la simulacion.
             * Parametro 1: Nivel en el que el seguimiento debe ser impreso,
             * utilizado Con Sim_system.set_trace_level () para controlar cuales
             * trazas se imprimiran. Parametro 2: Menasaje
             *
             */
            sim_trace(1, "Valor de i en el  bucle: " + i);
        }
        System.out.println("Saliendo del body del sender ");
    }
}

/**
 * Clase del receiver
 *
 * @author eagle
 */
class Sink extends Sim_entity {

    private Sim_port in;
    private int index;
    private int state;
    public static final int SINK_BLOCKED = 0;
    public static final int SINK_OK = 1;

    public Sink(String name, int index, int state) {
        super(name);
        this.index = index;
        this.state = state;
        //in: Nombre para identificar el puerto
        in = new Sim_port("in");
        add_port(in);
    }

    @Override
    public void body() {
        Sim_event ev = new Sim_event();
        int i = 0;

        System.out.println("Creando el body del Receiver:");
        while (Sim_system.running()) {
            i++;
            if (i > 100) {
                break;
            }
            sim_wait(ev);
            sim_hold(1.234);
            sim_schedule(in, 0.0, 1);
            System.out.println("");
        }
        System.out.println("saliendo del body Del Receiver..");
    }
}
